package yt.demo.appcorequartz.impl;

import jakarta.annotation.PostConstruct;
import org.quartz.CronExpression;
import org.quartz.CronTrigger;
import org.quartz.SchedulerException;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import yt.demo.appcommonbean.exception.LogicException;
import yt.demo.appcommonbean.http.DeleteRequest;
import yt.demo.appcommonbean.http.DetailRequest;
import yt.demo.appcommondb.dto.SplitPageDTO;
import yt.demo.appcommondb.vo.PageVO;
import yt.demo.appcorequartz.entity.QuartzJob;
import yt.demo.appcorequartz.entity.QuartzLog;
import yt.demo.appcorequartz.enums.JobStatus;
import yt.demo.appcorequartz.scheduler.QuartzManage;
import yt.demo.appcorequartz.service.ICronService;

import java.util.List;
import java.util.Objects;

@Service
public class CronService implements ICronService {

    private final QuartzJobService quartzJobService;
    private final QuartzManage quartzManage;

    @Autowired
    public CronService(QuartzJobService quartzJobService, QuartzManage quartzManage) {
        this.quartzJobService = quartzJobService;
        this.quartzManage = quartzManage;
    }

    @PostConstruct
    public void init() {
        List<QuartzJob> jobList = quartzJobService.getList(null, w -> {
            w.in(QuartzJob::getStatus, JobStatus.JOB_RUN.getStatus(), JobStatus.JOB_STOP.getStatus());
        }, null);
        jobList.forEach(quartzJob -> {
            CronTrigger cronTrigger = quartzManage.getCronTrigger(quartzJob.getId());
            if (Objects.isNull(cronTrigger)) {
                quartzManage.createJob(quartzJob);
            } else {
                quartzManage.updateJob(quartzJob);
            }
        });
    }

    public QuartzJob getById(Integer id) {
        return quartzJobService.detail(id);
    }

    @Override
    public PageVO<QuartzJob> getPageList(SplitPageDTO dto, QuartzJob params) {
        return quartzJobService.getPageList(dto, params,  w->w.orderByDesc(QuartzJob::getId), null);
    }

    public void create(QuartzJob quartzJob) {
        try {
            if (!CronExpression.isValidExpression(quartzJob.getCronExpres())) {
                throw new Exception("无效的 Cron 表达式" );
            }
            quartzJobService.create(quartzJob);
            if (quartzJob.getId() > 0) {
                quartzManage.createJob(quartzJob);
            }
        } catch (Exception e) {
            throw new LogicException(e.getMessage());
        }
    }

    public void update(QuartzJob quartzJob) {
        try {
            if (!CronExpression.isValidExpression(quartzJob.getCronExpres())) {
                throw new Exception("无效的 Cron 表达式" );
            }
            quartzJobService.update(quartzJob);
            if (quartzJob.getId() > 0) {
                quartzManage.updateJob(quartzJob);
            }
        } catch (Exception e) {
            throw new LogicException(e.getMessage());
        }

    }

    public void delete(DeleteRequest req){
        quartzJobService.delete(req);
        quartzManage.deleteJob(Math.toIntExact(req.getId()));
    }

    public void updateStatus(QuartzJob quartzJob) {
        try {
            if (quartzJob.getStatus() == JobStatus.JOB_RUN.getStatus()) {
                resume(quartzJob.getId());
            } else if (quartzJob.getStatus() == JobStatus.JOB_STOP.getStatus()) {
                pause(quartzJob.getId());
            }
        } catch (Exception e) {
            throw new LogicException("修改失败:" + e.getMessage());
        }
    }

    public void run(DetailRequest req){
        QuartzJob quartzJob = getById(Math.toIntExact(req.getId()));
        quartzManage.run(quartzJob);
    }

    /**
     * 暂停任务
     */
    public void pause(Integer id) {
        QuartzJob quartzJob = getById(id);
        if (!Objects.isNull(quartzJob)) {
            quartzJob.setStatus(JobStatus.JOB_STOP.getStatus());
            quartzJobService.update(quartzJob);
            quartzManage.checkStop(quartzJob);
        }
    }

    /**
     * 恢复任务
     */
    public void resume(Integer id) {
        QuartzJob quartzJob = getById(id);
        if (!Objects.isNull(quartzJob)) {
            quartzJob.setStatus(JobStatus.JOB_RUN.getStatus());
            quartzJobService.update(quartzJob);
            quartzManage.resumeJob(id);
        }
    }


}
